export * from "./ali-oss.js"
export * from "./check"
export * from "./crypto.class.js"
export * from "./public.js"
export * from "./spark-md5.js"
export * from "./storage.js"

import dayjs from "dayjs"
import router from '@/router.js'

/**
 * 流量换算 字节格式化
 * @param {Number} bytes 字节数
 * @param {Number} precision 保留小数点后位数
 * @param {Number} base 进制 1000 | 1024
 * @returns {String}
 */
export const fmtBytes = (bytes, precision, base) => {
  var precision = precision == 0 ? 0 : (precision || 2);
  var base = base || 1000;
  var units = ['B', 'KB', 'MB', 'GB', 'TB'];
  var bytes_zf = '';
  if (bytes < 0) {
    bytes_zf = '-';
    bytes = -bytes
  }
  bytes = Math.max(bytes, 0);
  var pow = Math.floor((bytes ? Math.log(bytes) : 0) / Math.log(base));
  var powIndex = Math.min(pow, units.length - 1);
  bytes /= Math.pow(base, powIndex);
  var bytes1 = bytes.toFixed(precision);
  if (bytes1 >= 1000 && powIndex < (units.length - 1)) {
    bytes1 = (bytes1 / 1000).toFixed(precision);
    powIndex++
  }
  return bytes_zf + bytes1 + units[powIndex];
}

/**
 * 货币格式化 https://www.zhangxinxu.com/wordpress/2019/09/js-intl-zh/
 * eg: 1111.1 => '1,111.1'
 * @param {Nmuber} price 价格，单位：分，1 元 = 100 分
 * @param {*} zero 为空时如何显示
 * @param {Number} fixed 精度
 */
export const fmtCurrency = (price, zero = 0, fixed = 2) => {
  if (!price) return zero

  const num = Number(price / 100).toFixed(fixed);
  return new Intl.NumberFormat(undefined, {
    minimumFractionDigits: fixed
  }).format(num)
}

/**
 * 时间戳格式化
 * @param {Number} ts 时间戳，支持秒和毫秒
 * @param {String} fmt 格式化字符串
 */
export const fmtTimestamp = (ts, fmt = 'YYYY-MM-DD HH:mm:ss') => {
  const t = ts < 1e10 ? ts * 1000 : ts
  return dayjs(t).format(fmt)
}

export const fmtTimestampRel = (ts) => {
  const t = dayjs(ts < 1e10 ? ts * 1000 : ts)
  const now = dayjs()
  const diff_ss = now.diff(t, 'second');
  const diff_mm = now.diff(t, 'minute');
  const diff_hh = now.diff(t, 'hour');
  const diff_DD = now.diff(t, 'day');
  const diff_MM = now.diff(t, 'month');
  const diff_YY = now.diff(t, 'year');

  if (diff_ss < 60) {
    return `${diff_ss} 秒前`;
  } else if (diff_mm < 60) {
    return `${diff_mm} 分钟前`;
  } else if (diff_hh < 24) {
    return `${diff_hh} 小时前`;
  } else if (diff_DD < 30) {
    return `${diff_DD} 天前`;
  } else if (diff_MM < 12) {
    return `${diff_MM} 个月前`;
  } else {
    return `${diff_YY} 年前`;
  }
}

// 深拷贝
export const deepCopy = (source) => {
  var sourceCopy = source instanceof Array ? [] : {};
  for (const item in source) {
    sourceCopy[item] = source[item] !== null && !(source[item] instanceof Date) && typeof source[item] === 'object' ? deepCopy(source[item]) : source[item];
  }
  return sourceCopy;
}

/**
 * 删除文件后缀名, eg: 'example.mp4.tar.gz' -> 'example'
 * @param {String} name 
 * @param {String} mod 'single' 删除单个后缀名 eg: 'example.mp4.tar.gz' -> 'example.mp4.tar'
 */
export const rmSuffix = (name, mod) => {
  if (!name) return ""
  if (mod === 'single') return name.replace(/\.[^/.]+$/, "")
  return name.replace(/\..*$/, "");
}

/**
 * 11 位手机号码脱敏处理, eg: '18812341234'-> '188****1234'
 * @param {String} mobile 
 */
export const maskMobile = (mobile) => {
  if (!mobile) return ""
  return mobile.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
}

/**
 * form 表单校验
 * @param {ref} ref 表单 ref
 */
export const validateForm = (ref) => {
  return new Promise((resolve, reject) => {
    if (!ref) return reject();
    ref?.value?.validate((valid, fields) => {
      if (valid) return resolve()
      return reject(fields)
    })
  })
}

// 根据value 返回字典的label
export function transformDict(
  dictArray,
  compareValue,
  compareKey = "value",
  valueKey = "label"
) {
  if (dictArray && dictArray.length > 0) {
    for (const i in dictArray) {
      if (dictArray[i][compareKey] == compareValue) {
        return dictArray[i][valueKey];
      }
    }
    return "";
  } else {
    return "";
  }
}

// 精确加
const accAdd = (arg1, arg2) => {
  let r1, r2, m
  try {
    r1 = arg1.toString().split('.')[1].length
  } catch (e) {
    r1 = 0
  }
  try {
    r2 = arg2.toString().split('.')[1].length
  } catch (e) {
    r2 = 0
  }
  m = Math.pow(10, Math.max(r1, r2))
  return (arg1 * m + arg2 * m) / m
}

// 精确减
const accSub = (arg1, arg2) => {
  var r1, r2, m, n
  try {
    r1 = arg1.toString().split(".")[1].length
  } catch (e) {
    r1 = 0
  }
  try {
    r2 = arg2.toString().split(".")[1].length
  } catch (e) {
    r2 = 0
  }
  m = Math.pow(10, Math.max(r1, r2))
  n = r1 >= r2 ? r1 : r2
  return (arg1 * m - arg2 * m) / m
}

// 精确乘 
const accMul = (arg1, arg2) => {
  if (!arg1 || !arg2 || !Number(arg1) || !Number(arg2)) return 0
  let m = 0
  let s1 = arg1.toString()
  let s2 = arg2.toString()
  try {
    m += s1.split('.')[1] ? s1.split('.')[1].length : ''
  } catch (e) { }
  try {
    m += s2.split('.')[1] ? s2.split('.')[1].length : ''
  } catch (e) { }
  return (Number(s1.replace('.', '')) * Number(s2.replace('.', ''))) / Math.pow(10, m)
}

// 精确除
const accDiv = (arg1, arg2) => {
  if (!arg1 || !arg2 || !Number(arg1) || !Number(arg2)) return 0
  let t1 = 0
  let t2 = 0
  let r1
  let r2
  try {
    t1 = arg1.toString().split('.')[1].length
  } catch (e) { }
  try {
    t2 = arg2.toString().split('.')[1].length
  } catch (e) { }
  r1 = Number(arg1.toString().replace('.', ''))
  r2 = Number(arg2.toString().replace('.', ''))
  return (r1 / r2) * Math.pow(10, t2 - t1)
}

// 精确计算: 加减乘除
export const calc = {
  add() { return Array.from(arguments).reduce((total, num) => accAdd(total, num)) },
  sub() { return Array.from(arguments).reduce((total, num) => accSub(total, num)) },
  mul() { return Array.from(arguments).reduce((total, num) => accMul(total, num)) },
  div() { return Array.from(arguments).reduce((total, num) => accDiv(total, num)) },
}

// 文件 MIME 类型
export const fileMIME = {
  isVideo: (type) => (type || '').includes('video'),
  isImage: (type) => (type || '').includes('image'),
  isAudio: (type) => (type || '').includes('audio'),
}

/**
 * a 标签下载功能
 * @param {String} URL 下载内容，URL || blob: URL || data: URL(base64)
 * @param {String} name 下载后的文件名称
 */
export const downloadTagA = ({ URL, name }) => {
  const elem = document.createElement('a')
  elem.download = name || new Date().getTime()
  elem.style.display = 'none'
  elem.href = URL
  document.body.appendChild(elem)
  elem.click()
  document.body.removeChild(elem)
}

/**
 * 防抖函数
 * @param {Function} fn
 * @param {Number} delay
 */
export const debounce = (fn, delay) => {
  let timer = null
  return function () {
    const context = this
    const args = arguments
    clearTimeout(timer)
    timer = setTimeout(function () {
      fn.apply(context, args)
    }, delay)
  }
}

/**
 * 节流函数
 * @param {Function} fn
 * @param {Number} delay
 * @returns
 */
export const throttle = (fn, delay) => {
  let lastTime = 0
  return function () {
    const context = this
    const args = arguments
    const nowTime = Date.now()
    if (nowTime - lastTime > delay) {
      fn.apply(context, args)
      lastTime = nowTime
    }
  }
}

/**
 * 跳转页面
 * @param {String | Number} v 路由参数
 * @param {String} target 跳转方式 _blank 打开新窗口
 */
export const toOpen = (v, target) => {
  if (typeof v === 'number') {
    router.go(v)
  }
  if (target === '_blank') {
    const url = router.resolve(v).href
    window.open(url, "_blank")
  } else {
    router.push(v)
  }
}